/*================================================================
 *   Copyright (C) 2021 All rights reserved.
 *   
 *   文件名称：thread.cc
 *   创 建 者：汉森伯逸
 *   创建日期：2021年04月26日
 *   描    述：
 *
 *================================================================*/

#include "log.h"
#include "thread.h"
#include "util/util.h"

namespace hsby{

/*
 * @brief 线程储存期对象, 用户将通过Thread提供的静态方法访问Thread对象
 */
static thread_local Thread* t_thread = nullptr;
static thread_local std::string t_thread_name = "UNKNOW";


/*
 * @brief 线程上下文构造函数
 */
Thread::Thread(std::function<void()> cb, const std::string& name) : name_(name), cb_(cb) {
    if (name.empty())
        name_ = "UNKNOW";
    int rt = pthread_create(&thread_, nullptr, &Thread::Run, (void*)this);
    if (rt){
        HSBY_LOG_SYSTEM_ERROR << "pthread_create thread fail, rt=" << rt
                              << " name=" << name_;
        throw std::logic_error("pthread_create error");
    }
    semaphore_.wait();
}

/*
 * @brief 线程上下文析构函数
 */
Thread::~Thread(){
    if (thread_){

        /*
         * @brief 将线程设置为unjoinable
         */
        pthread_detach(thread_);
    }
}

void Thread::Dump(std::ostream &os) const {
    os << "Thread{" << HSBY_VARS_EXP(id_, name_) << "}";
}

/*
 * @brief 线程正文
 */
void* Thread::Run(void *arg){
    Thread* thread = (Thread*)arg;
    thread->id_ = hsby::GetThisThreadId();
    SetThread(thread);
    SetThreadName(thread->GetName());
    pthread_setname_np(pthread_self(), thread->name_.c_str());

    std::function<void()> cb;
    cb.swap(thread->cb_);      // 保险操作，清空线程上下文中的m_cb

    thread->semaphore_.post();     // 在此释放线程上下文初始化

    // 线程上下文中的
    cb();
    return 0;
}

/*
 * @brief 取出线程的上下文
 */
Thread* Thread::GetThread(){
    return t_thread;
}

void Thread::SetThread(Thread* thread) {
    t_thread = thread;
}

/*
 * @brief 取得本线程名
 */
const std::string& Thread::GetThreadName(){
    return t_thread_name;
}

/**
 * @brief  设置线程生存期中到t_thread_name对象
 * @param  name  参数1
 */
void Thread::SetThreadName(const std::string& name){
    t_thread_name = name;
}

/*
 * @brief 阻塞等待回收线程
 */
void Thread::join(){
    if (thread_){
        int rt = pthread_join(thread_, nullptr);
        if (rt){
            HSBY_LOG_SYSTEM_ERROR << "pthread_join thread fail, rt=" <<
                                  " name=" << name_;
            throw std::runtime_error("pthread_join error");
        }
        thread_ = 0;
    }
}

}// namespace hsby